# -*- coding: UTF-8 -*-
import json
import os
import threading
import time
import traceback
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from InterfaceAuto.commonalKeys import syspublic
from configuration.logger import logger


class App():
    """
    Creator：Dou
    封装app关键字

    """

    def __init__(self, writer):
        """
        初始化实例变量
        """

        self.writer = writer  # 写入Excel对象
        self.row = 0  # 记录关键字运行时,写入Excel的行
        self.conf = {}  # 保存appium和app启动参数
        self.driver = None  # app驱动

    def start_appium(self, port=''):
        """
        多线程启动appium服务
        """
        if port == '':
            port = '4723'
        self.conf['port'] = port

        def runappium(port='4723'):
            #  这里配置自己本地appium-desktop安装路径
            # cmd = r"node E:\Appium\resources\app\node_modules\appium\build\lib\main.js -p " + port
            cmd = r"D:\appiumservier\appium.cmd" + port
            os.popen(cmd).read()


        # 创建子线程
        th = threading.Thread(target=runappium, args=(port,))
        # 启动线程
        th.start()
        time.sleep(5)
        self.__writerexcel(True, "启动成功")

    def start_app(self, conf):
        """
        启动程序
        :param conf: 启动参数配置
        :return: True of False
        """
        try:
            conf = conf.replace(r'\n', '')
            conf = eval(conf)
            self.__writerexcel(True,"启动start_app成功")
        except Exception as e:
            self.__writerexcel(False, traceback.format_exc())
            self.writer.save_close()
            self.stop_appium(self.conf['port'])
            logger.info("启动start_app失败请检查")
            exit(-1)
            return False

        try:
            self.conf.update(conf)
            self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", conf)
            self.driver.implicitly_wait(10)
            self.__writerexcel(True, "等待成功")
        except Exception as e:
            self.__writerexcel(False, traceback.format_exc())
            self.writer.save_close()
            self.stop_appium(self.conf['port'])
            logger.info("启动start_app失败请检查")
            exit(-1)
            return False

    def stop_appium(self, port=''):
        """
        关闭appiumservise
        """
        try:
            if port == '':
                port = '4723'

            pid = os.popen('netstat -aon | findstr LISTENING | findstr ' + port).read()
            pid = pid.split(' ')
            if len(pid) < 2:
                return
            else:
                pid = pid[len(pid) - 1]

            res = os.popen('taskkill /F /PID ' + pid).read()
            logger.info(res)
            self.__writerexcel(True,"关闭appiumservise成功")

        except Exception as e:
            logger.exception(e)
            self.__writerexcel(False, traceback.format_exc())
            return False

    def implicitwaitele(self, locate):
        """
        使用隐式等待, 等待元素出现

        """
        ele = self.__find_ele(locate)
        if ele is None:
            self.__writerexcel(True, "等待失败")
        else:
            self.__writerexcel(True, "等待成功")

    def input(self, locateStatement, content, t=''):
        """
        输入内容
        :param locateStatement: 定义表达式
        ：param t: 等待时间
        :param content: 输入的内容
        :return:
        """
        if t == '':
            t = 5
            self.sleep(int(t))

        ele = self.__find_ele(locateStatement)
        if ele is None:
            self.__writerexcel(False, self.e)
            return False
        try:
            ele.send_keys(content)
            self.__writerexcel(True, "输入成功")
            return True
        except Exception as e:
            logger.exception(e)
            self.__writerexcel(False, traceback.format_exc())
            return False

    def click(self, locateStatement, t=''):
        """
        点击方法
        :param locateStatement: 定位表达式
        :param t : 等待时间 default 秒
        :return:
        """
        if t == '':
            t = 5
            self.sleep(int(t))

        ele = self.__find_ele(locateStatement)
        if ele is None:
            self.__writerexcel(False, self.e)
            return False
        try:
            ele.click()
            self.__writerexcel(True, "click成功")
            return True
        except Exception as e:
            logger.exception(e)
            self.__writerexcel(False, traceback.format_exc())
            return False

    def slide(self, x1, y1, t=''):
        """
        滑动方法
        :param x1: 纵坐标
        :param y1: 横坐标
        :param t: 等待时间
        :return:
        """
        if t == '':
            t = 5
            self.sleep(int(t))
        try:
            x1 = x1.split(',')
            y1 = y1.split(',')
            TouchAction(self.driver).press(x=int(x1[0]), y=int(x1[1])).move_to(x=int(y1[0]),
                                                                               y=int(y1[1])).release().perform()
            self.__writerexcel(True, "滑动成功")
        except Exception as e:
            logger.exception(e)
            self.__writerexcel(False, traceback.format_exc())
            self.__writerexcel(False, "滑动失败")
            return False

    def adb_click(self, x, y, t=''):
        """

        """
        if t == '':
            t = 5
        time.sleep(int(t))

        try:
            logger.info('adb shell input tap %s %s' % (x, y))
            os.popen('adb shell input tap %s %s' % (x, y)).read()
            self.__writerexcel(True, "adb点击成功")
            return True
        except Exception as e:
            logger.exception(e)
            self.__writerexcel(False, traceback.format_exc())
            self.__writerexcel(False, "adb点击失败")
            return False

    def sleep(self, t):
        """
        强制等待
        :param t: 时间，单位s
        :return: 返回成功失败
        """
        try:
            time.sleep(int(t))
            self.__writerexcel(True, "等待成功")
            return True
        except Exception as e:
            self.__writerexcel(False, traceback.format_exc())
            return False

    def get_text(self, locateStatement, params, t=''):
        """
        获取元素文本内容，并保存后为关联后参数名
        :param locateStatement: 定义表达式
        :param t:等待时间
        :param params: 保存后的参数名
        :return: true or false
        """
        if t == '':
            t = 5
            self.sleep(int(t))

        ele = self.__find_ele(locateStatement)
        if ele is None:
            self.__writerexcel(False, self.e)
            return False
        try:
            text = ele.text
            # 设置到关联字典里面
            syspublic.relations[params] = text
            self.__writerexcel(True, syspublic.relations[params])
            return True
        except Exception as e:
            logger.exception(e)
            self.__writerexcel(False, traceback.format_exc())
            return False

    def assert_contains(self, expect, actual):
        """
        断言包含某个文本内容
        :param expect: 预期结果
        :param actual: 实际结果
        :return: True or False
        """
        # 关联实际结果
        actual = self.__getrelations(actual)
        expect = self.__getrelations(expect)
        if actual.__contains__(str(expect)):
            self.__writerexcel(True, actual)
            return True

        else:
            self.__writerexcel(False, actual)
            return False

    def __find_ele(self, locate):
        """
        通过定位器找元素
        :param locate: xpath,id,accessibility_id
        :return: 返回找到的元素
        """
        try:
            if locate.startswith("/"):
                ele = self.driver.find_element_by_xpath(locate)
            elif locate.index(':id/') > 0:
                ele = self.driver.find_element_by_id(locate)
            else:
                ele = self.driver.find_element_by_accessibility_id(locate)
        except Exception as e:
            self.e = traceback.format_exc()
            return None

        return ele

    def __getrelations(self, params):
        """
        使用关联
        :param params: 需要关联的参数
        :return:  关联后的字符串
        """
        if params is None:
            return None

        for key in syspublic.relations.keys():
            params = params.replace('{' + key + '}', str(syspublic.relations[key]))
        return params

    def __writerexcel(self, status, msg):
        """
        写入关键字运行结果
        :param status: 运行状态
        :param msg: 实际结果

        """
        if status is True:
            self.writer.write(self.row, 7, "PASS", 3)
        else:
            self.writer.write(self.row, 7, "FAIL", 2)
        self.writer.write(self.row, 8, str(msg))

    def quit(self):
        """
        关闭app连接
        :return:
        """
        try:
            self.driver.quit()
            self.__writerexcel(True,"退出成功")
            return True
        except Exception as e:
            self.__writerexcel(False,traceback.format_exc())
            return False